<?php
namespace Api\Controller;

use \Common\Library\Job\Commission;
class WXController extends APIController
{	

    //微信预支付
    public function prePay(){
        $obj = D('Base');
        $order_num = I('param.order_num');
        /*数据验证*/
        $info = $obj->getInfo('id,pay_price,is_pay,user_id,status,crdate',array('order_num' => $order_num),'order');
        if(!$info){
            $this->res_data['code_key'] = 'lawless';
            $this->apiReply();
        }
        //判断订单状态
        if($info['status'] != 1){
            $this->res_data['code_key'] = 'order_status_error';
            $this->apiReply();
        }else{
            //订单是否已过支付时间 自创建时间开始 15分钟内支付有效
            $expired = 900;
            $info['crdate'] = strtotime($info['crdate']);
            if(time() - $info['crdate'] >= $expired){
                //设置订单失效
                $data = [
                    'remark' => '订单超时未支付，已失效',
                    'status' => 7,
                    'tstamp' => time()
                ];
                $num = M('order')->where(array('id' => $info['id']))->save($data);
                if(!$num){
                    debug(M('order')->_sql());
                    $this->res_data['code_key'] = 'fail';
                    $this->apiReply();
                }else{
                    $this->res_data['code_key'] = 'order_expired';
                    $this->apiReply();
                }
            }
        }
        if($info['is_pay'] ==1){
            $this->res_data['code_key'] = 'order_paied';
            $this->apiReply();
        }
        /*获取用户openid*/
        $user_info = $obj->getInfo('openid',array('id' => $info['user_id']),'member');

        /*生成预支付订单号*/
        /*$salt = $obj->CreateInviteCode();
        $pre_num = $order_num.'_'.$salt;*/
        $pre_num = $order_num;
        static $params = array();
        static $res = array();
        /*数据整理请求接口*/
        $params = array(
            'appid' => C('Config.appid'),
            'mch_id' => C('Config.mchid'),
            'nonce_str' => $obj->CreateInviteCode(),
            'body' => '支付订单',
            'out_trade_no' => $pre_num,
            'total_fee' => $info['pay_price']*100,
            'spbill_create_ip' => $_SERVER['REMOTE_ADDR'],
            'notify_url' => C('DOMAIN_URL').'Api/WX/notify',
            'trade_type' => 'JSAPI',
            'openid' => $user_info['openid'],
            );
        $params = $this->getSignParams($params);
        $params = $this->createLinkString($params,C('Config.key'));
        $url = 'https://api.mch.weixin.qq.com/pay/unifiedorder';
        $result = curl($url,$params,'post','xml');
        /*返回结果验证*/
        $result = (array)simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
        
        if($result['return_code'] === 'SUCCESS'){
            $res = array(
                'appId' => C('Config.appid'),
                'timeStamp' => "'".time()."'",
                'nonceStr' => $result['nonce_str'],
                'package' => "prepay_id=". $result['prepay_id'],
                'signType' => 'MD5'
             );
            $res = $this->getSignParams($res);
            $res = $this->createLinkString($res,C('Config.key'));
            $res['paySign'] = $res['sign'];
            unset($res['sign']);

        }else{
            debug($result);
            $this->res_data['code_key'] = 'sys_busy';
            $this->apiReply();
        }
        
        $this->res_data['data'] = $res;
        $this->apiReply();

    }

    /**
     * 微信支付--回调处理
     */
    public function notify(){
        try{
            $msg = array(
                'content' => file_get_contents('php://input'),
                'crdate' => date('Y-m-d H:i:s',time()),
                );
            M('log')->add($msg);
            $xml = file_get_contents('php://input');
            $result = (array)simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA);
            debug($result,'notify.txt');
            $res = $result['return_code'];
            if($res == 'SUCCESS'){
                //支付金额验证
                static $order_num = array();
                $order_num = explode('_', $result['out_trade_no']);
                //商户订单号
                $out_trade_no = $order_num[0];
                $flag = $this->checkTotalFee($result['transaction_id'],$out_trade_no);
                if(!$flag){
                   $res = array(
                        'return_code' => 'FAIL',
                        'return_msg' => '支付金额被篡改'
                    );
                    header('Content-Type:text/xml; charset=utf-8');
                    exit($this->arrayToXml($res)); 
                }
                $this->afterPay($result['transaction_id'],$out_trade_no);
                $res = array(
                    'return_code' => 'SUCCESS',
                    'return_msg' => 'OK',
                );
                header('Content-Type:text/xml; charset=utf-8');
                exit($this->arrayToXml($res));
            }
        }catch(\Exception $e){
            debug($e,'notify.txt');
        }
    }

    /**
     * 验证签名
     * @param $params
     * @param $sign
     * @return bool
     */
    public function verifySign($params, $sign){
        $params = $this->getSignParams($params);
        $params = $this->createLinkString($params);

        return $params['sign'] === $sign;
    }

    /**
     * 把数组所有元素，按照“参数=参数值”的模式用“&”字符拼接成字符串
     * @param $params
     * @param $mkey
     * @return string
     */
    public function createLinkString($params,$mkey){
        $arg  = "";
        foreach($params as $key => $val){
            $arg.=$key."=".$val."&";
        }
        $params['sign'] = strtoupper(MD5($arg.'key='.$mkey));
        return $params;
    }

    /**
     * 获取参与签名的参数
     * @param $params
     * @return array
     */
    public function getSignParams($params){
        $tmp = array();
        foreach($params as $key => $val){
            if($key !== 'sign' && $val !== ''){
                $tmp[$key] = $val;
            }
        }

        ksort($tmp);
        reset($tmp);

        return $tmp;
    }

    /**
     * 返回结果数组转XML
     * @param $param
     * @return string
     */
    public function arrayToXml($param){
        $str = '<xml>';
        foreach($param as $key => $val){
            if(is_numeric($val)){
                $str .= "<{$key}>{$val}</{$key}>";
            }else{
               $str .= "<{$key}><![CDATA[{$val}]]></{$key}>"; 
           }
            
            
        }
        $str .= "</xml>";

        return $str;
    }

    /**
     * 微信支付后支付金额验证
     */
    public function checkTotalFee($transaction_id,$order_num){
        return true;
        $obj = D('APIOrder');
        $url = 'https://api.mch.weixin.qq.com/pay/orderquery';
        $params = array(
            'appid' => $this->appId,
            'mch_id' => $this->mch_id,
            'transaction_id' => $transaction_id,
            'nonce_str' => $this->nonce_str,
            'appid' => $this->appId,
            'sign_type' => $this->sign_type,
            );
        $params = $this->getSignParams($params);
        $params = $this->createLinkString($params);
        $result = curl($url,$params,'post','xml');

        /*返回结果验证*/
        $result = (array)simplexml_load_string($result, 'SimpleXMLElement', LIBXML_NOCDATA);
        if($result['return_code'] == 'SUCCESS'){
            $res = $obj->checkInfo(array('order_num' => $order_num,'pay_price' => $result['total_fee']*0.01,'is_pay' => 0),'order');
            if(!$res){
                return false;
            }
            return true;
        }else{
            return false;
        }
    }
    
    /**
     * 微信支付后处理数据
     */
    public function afterPay($transaction_id,$order_num,$num = 1){
        try{
            $model = new \Think\Model;
            $model->startTrans();
            if($num < 4){
                $obj = M('Order');
                $order = $obj->where(array('order_num' => $order_num))->find();
                /*修改订单状态*/
                $data = array(
                    'status' => 2,
                    'is_pay' => 1,
                    'pay_time' => time(),
                    'wx_num' => $transaction_id,
                    'tstamp' => time(),
                );
                $flag = $obj->where(array('id' => $order['id']))->save($data);
                if(!$flag){
                    debug('修改订单状态失败');
                    debug($obj->_sql());
                    $model->rollback();
                    ++$num;
                    return $this->afterPay($transaction_id,$order_num,$num);
                }
                $num = true;
                //使用优惠券则修改优惠券的使用状态-修改优惠券的状态在订单发货时处理
                /*if($order['user_coupon_id']){
                    $param = [
                        'used_time' => time(),
                    ];
                    $num = M('user_coupon')->where(array('id' => $order['user_coupon_id']))->save($param);
                    if(!$num){
                        debug('修改优惠券状态失败');
                        debug(M('user_coupon')->_sql());
                        $model->rollback();
                        ++$num;
                        return $this->afterPay($transaction_id,$order_num,$num);
                    }
                }*/
                //判断是否为开团订单(只判断普通团跟神秘团)
                $Group = M('group');
                $info = $Group->where(array('id' => $order['group_id']))->find();
                //,'user_id' => $order['user_id'],'type' => ['IN',[1,2]]
                if(($info['user_id'] == $order['user_id']) && (in_array($info['type'],[1,2]))){
                    //获取活动的时效期
                    $activity = M('activity')->find($info['activity_id']);//where(array('id' => $info['activity_id']))->getField('expired');
                    $expired = time() + $activity['expired'] * 60 * 60;
                    $edit_data = [
                        'state' => 1,
                        'start' => time(),
                        'expired' => $expired
                    ];
                    $group_flag = $Group->where(array('id' => $info['id']))->save($edit_data);
                    if(!$group_flag){
                        debug('修改团活动状态失败');
                        debug($Group->_sql());
                        $model->rollback();
                        ++$num;
                        return $this->afterPay($transaction_id,$order_num,$num);
                    }
                    //判断是否为神秘团且设置开团发券
                    if($info['type'] == 2 && $activity['group_coupon_id']){
                        $coupon_info = M('Coupon')->find($info['group_coupon_id']);
                        $param = [
                            'user_id' => $order['user_id'],
                            'coupon_id' => $coupon_info['id'],
                            'name' => $coupon_info['name'],
                            'type' => $coupon_info['type'],
                            'full_money' => $coupon_info['full_money'],
                            'goods_id' => $coupon_info['goods_id'],
                            'money' => $coupon_info['money'],
                            'crdate' => time(),
                            'expired' => (time() + $coupon_info['expired'] * 86400)
                        ];
                        $UserCoupon = M('user_coupon');
                        $user_coupon_id = $UserCoupon->add($param);
                        //保存失败,事务回滚
                        if(!$user_coupon_id){
                            debug('发送优惠券失败');
                            debug($UserCoupon->_sql());
                            $model->rollback();
                            ++$num;
                            return $this->afterPay($transaction_id,$order_num,$num);
                        }
                    }
                }
                //判断是否满团
                //该团下的所有支付订单 ->当前支付回调的订单处于事务中 还未提交
                $count = $obj->where(array('is_pay' => 1,'group_id' => $info['id']))->count()?:0;
                if($count == $info['num']){
                    //设置满团时间
                    $num = $Group->where(array('id' => $info['id']))->save(array('complete_time' => time()));
                    if(!$num){
                        debug('修改团活动状态失败');
                        debug($Group->_sql());
                        $model->rollback();
                        ++$num;
                        return $this->afterPay($transaction_id,$order_num,$num);
                    }
                    //神秘团满团设置开团人为超级团长
                    if($info['type'] == 2){
                        $Member = M('member');
                        $member_info = $Member->find($order['user_id']);
                        if(!$member_info['is_colonel']){
                            $member_num = $Member->where(array('id' => $order['user_id']))->save(array('is_colonel' => 1));
                            if(!$num){
                                debug('设置超级团长失败');
                                debug($Member->_sql());
                                $model->rollback();
                                ++$num;
                                return $this->afterPay($transaction_id,$order_num,$num);
                            }
                        }
                    }
                    //发送满团优惠券
                    if($info['coupon_id']){
                        $coupon_info = M('Coupon')->find($info['coupon_id']);
                        $where = ['group_id' => $info['id']];
                        //判断新团是否为神秘团 神秘团团长不发满团优惠券
                        if($info['type'] == 2){
                            //获取团长信息
                            $leader_user_id = $Group->where(array('id' => $info['id']))->getField('user_id');
                            $where = ['user_id' => ['neq' => $leader_user_id]];
                        }
                        $UserCoupon = M('user_coupon');
                        //获取所有要发券的用户id
                        $user_ids = $obj->where($where)->Field('user_id')->select();
                        if($user_ids){
                            foreach ($user_ids as $key => $value) {
                                $param = [
                                    'user_id' => $value['user_id'],
                                    'coupon_id' => $coupon_info['id'],
                                    'name' => $coupon_info['name'],
                                    'type' => $coupon_info['type'],
                                    'full_money' => $coupon_info['full_money'],
                                    'goods_id' => $coupon_info['goods_id'],
                                    'money' => $coupon_info['money'],
                                    'crdate' => time(),
                                    'expired' => (time() + $coupon_info['expired'] * 86400)
                                ];
                                $user_coupon_id = $UserCoupon->add($param);
                                //保存失败,事务回滚
                                if(!$user_coupon_id){
                                    debug('发送优惠券失败');
                                    debug($UserCoupon->_sql());
                                    $model->rollback();
                                    ++$num;
                                    return $this->afterPay($transaction_id,$order_num,$num);
                                }
                            }
                        }
                    }
                    //若为超级团长团,生成佣金记录
                    if($order['type'] == 3){
                        $class = new Commission($order['group_id']);
                        $class->handle();
                    }

                }
                debug('支付回调处理在第'.$num.'次处理成功');
                $model->commit();
            }else{
                debug('支付回调处理超过3次未成功');
            }
        }catch(\Excepiton $e){
            $model->rollback();
            debug($e,'notify_log.txt');
        }
    }

	
}